#!/bin/bash
#
# Script to install multiple instances of Tungsten Replicator on
# multiple instances of MySQL in the same host
#
# Copyright (c) 2011 Continuent, Inc.  All rights reserved.
# Released under the New BSD License

# ---- defaults ---- 
HOW_MANY=3
MYSQL_VERSION=5.5.13
TUNGSTEN_BASE=$HOME/tsb2/
TUNGSTEN_SERVICE=tsandbox
MYSQL_BASE_PORT=7100
MYSQL_GROUP_DIR=tr_dbs
THL_BASE_PORT=12110
RMI_BASE_PORT=10100
TSANDBOX_PREFIX=db
VERSION=1.0.8

# --- Do not modify anything below this line

# checking for MySQL Sandbox
MMS=$(which make_multiple_sandbox)
if [ -z $MMS ]
then
    echo "Can't find  make_multiple_sandbox. Perhaps MySQL Sandbox is not installed"
    echo "Get it from CPAN or from http://mysqlsandbox.net"
    exit 1
fi

CURDIR=$(dirname $0)
if [ "$CURDIR" == "." ]
then
    CURDIR=$PWD
fi

# Check for minimum version

if [ -f $CURDIR/../.manifest ]
then
    BUILD=$(grep BUILD_NUMBER $CURDIR/../.manifest | awk '{print $2}')
    MIN_BUILD=360
    if [ $BUILD -lt $MIN_BUILD ]
    then
        echo "Builds earlier than $MIN_BUILD can't be used with this version of tungsten-sandbox"
        echo "Your build is $BUILD - Please download a more recent version "
        exit 1
    fi
else
    echo "could not find .manifest"
    exit 1
fi

# shflags is a command line processor
if  [ -f $CURDIR/shflags  ]
then
    SHFLAGS=$CURDIR/shflags
else
    echo "WARNING: shflags not found - Command line option processing is not available"
    echo "Get it from http://code.google.com/p/shflags/"
    echo "In the meantime, edit this script to change the defaults"
    if [ "$1" != "" ]
    then
        exit 1
    fi
fi

if [ "$SHFLAGS" != "" ]
then
    . $SHFLAGS
    # macro        name            default           help text                            short name
    # ------------ --------------- ----------------- -----------------------------------  -----------
    DEFINE_integer 'nodes'         $HOW_MANY         'how many nodes to install'          'n'
    DEFINE_string  'mysql_version' $MYSQL_VERSION    'which MySQL version to use'         'm'
    DEFINE_string  'tungsten_base' $TUNGSTEN_BASE    'where to install the sandbox'       't'
    DEFINE_string  'group_dir'     $MYSQL_GROUP_DIR  'sandbox group directory name'       'd'
    DEFINE_string  'tsb_prefix'    $TSANDBOX_PREFIX  'Tungsten Sandbox prefix'       'x'
    DEFINE_string  'service'       $TUNGSTEN_SERVICE 'how the service is named'           's'
    DEFINE_integer 'base_port'     $MYSQL_BASE_PORT  'port base for MySQL sandbox nodes'  'P'
    DEFINE_integer 'thl_port'      $THL_BASE_PORT    'port for the THL service'           'l' 
    DEFINE_integer 'rmi_port'      $RMI_BASE_PORT    'port for the RMI service'           'r' 
    DEFINE_boolean 'version'       false             'show Tungsten sandbox version'      'v' 
    DEFINE_boolean 'help'          false             'show Tungsten sandbox help'         'h' 

    # parse the command-line
    FLAGS "$@" || exit 1
    eval set -- "${FLAGS_ARGV}"
    # -------------------------------------------------------------------------------------
    MYSQL_VERSION=$FLAGS_mysql_version
    TUNGSTEN_BASE=$FLAGS_tungsten_base
    MYSQL_GROUP_DIR=$FLAGS_group_dir
    TUNGSTEN_SERVICE=$FLAGS_service
    MYSQL_BASE_PORT=$FLAGS_base_port
    TSANDBOX_PREFIX=$FLAGS_tsb_prefix
    THL_BASE_PORT=$FLAGS_thl_port
    RMI_BASE_PORT=$FLAGS_rmi_port
    HOW_MANY=$FLAGS_nodes
fi

if [ "$FLAGS_version" == "0" ]
then
    echo "tungsten-sandbox - version $VERSION"
    echo "(C) Giuseppe Maxia, 2011 for Continuent, Inc"
    echo "released under the New BSD License"
    exit
fi

#
# Setting the initial values for the ports used by the sandbox
#
MASTER_MYSQL_PORT=$(($MYSQL_BASE_PORT+1))
MASTER_THL_PORT=$(($THL_BASE_PORT+1))
MASTER_RMI_PORT=$(($RMI_BASE_PORT+2))

#
# Checking that the MySQL version exists
#
if [ ! -d $HOME/opt/mysql/$MYSQL_VERSION ]
then
    echo "$HOME/opt/mysql/$MYSQL_VERSION not found"
    exit 1
fi

#
# The default tungsten home must exist
#
if [ ! -d  $TUNGSTEN_BASE ]
then
    echo "directory $TUNGSTEN_BASE not found"
    exit 1
fi
if [ "$TUNGSTEN_BASE" == "$HOME" ]
then
    echo "directory \$TUNGSTEN_BASE cannot be \$HOME"
    exit 1
fi

#
# Looking for tungsten-installer script
#
TUNGSTEN_INSTALLER=$CURDIR/tungsten-installer
if [ ! -x $TUNGSTEN_INSTALLER ]
then
    if [ -d tools ]
    then
        TUNGSTEN_INSTALLER=./tools/tungsten-installer
    elif [ -d tungsten ]
    then
        TUNGSTEN_INSTALLER=./tungsten/tools/tungsten-installer
    fi
fi

if [ ! -x $TUNGSTEN_INSTALLER ]
then
    echo "Could not find tungsten-installer"
    exit 1
fi

#
# ------------------ POINT OF NON RETURN ---------------------
#
# After this line, modifications start to happen in the system
#
# ------------------------------------------------------------

#
# Installing the databases necessary for the sandbox
#
export NODE_OPTIONS='-c log-bin=mysql-bin -c innodb_flush_log_at_trx_commit=2 -c max_allowed_packet=48M'

if [[ $MYSQL_VERSION < '5.5' ]]
then
    NODE_OPTIONS="$NODE_OPTIONS -c default-storage-engine=innodb"
fi

make_multiple_sandbox \
    --how_many_nodes=$HOW_MANY --sandbox_base_port=${MYSQL_BASE_PORT} \
    --group_directory=$MYSQL_GROUP_DIR $MYSQL_VERSION

function myseq
{
    low_limit=$1
    hi_limit=$2
    step=$3
    if [ -z $step ]
    then
        step=1
    fi
    if [  $low_limit -gt $hi_limit ]
    then
        echo "low limit should be smaller than high limit"
        exit -1
    fi
    counter=$low_limit
    while [ $counter -le $hi_limit ]
    do
        echo $counter
        counter=$(($counter+$step))
    done
}

#
# Add the privileges needed to run Tungsten
#
for N in $(myseq 1 $HOW_MANY)
do
    $HOME/sandboxes/$MYSQL_GROUP_DIR/n$N -u root -e 'update mysql.user set Grant_priv="Y" where user="msandbox"; flush privileges'
    # $HOME/sandboxes/$MYSQL_GROUP_DIR/n$N -u root -e 'set global general_log=1'
done

#
# Clean up anything from the sandbox home
#

rm -rf $TUNGSTEN_BASE/$TSANDBOX_PREFIX*
rm -f $TUNGSTEN_BASE/n?
rm -f $TUNGSTEN_BASE/{replicator,trepctl,clear,use,send_kill,status,start,stop}_all
rm -f $TUNGSTEN_BASE/db_{clear,use,send_kill,status,start,stop}_all

mkdir $TUNGSTEN_BASE/${TSANDBOX_PREFIX}1

#
# Installs the master
#

$TUNGSTEN_INSTALLER \
  --master-slave \
  --cluster-hosts=127.0.0.1 \
  --master-host=127.0.0.1 \
  --datasource-port="${MASTER_MYSQL_PORT}" \
  --datasource-user=msandbox \
  --datasource-password=msandbox \
  --home-directory=$TUNGSTEN_BASE/${TSANDBOX_PREFIX}1 \
  --datasource-log-directory=$HOME/sandboxes/$MYSQL_GROUP_DIR/node1/data \
  --datasource-mysql-conf=$HOME/sandboxes/$MYSQL_GROUP_DIR/node1/my.sandbox.cnf \
  --service-name=$TUNGSTEN_SERVICE \
  --thl-directory=$TUNGSTEN_BASE/${TSANDBOX_PREFIX}1/tlogs \
  --thl-port=$MASTER_THL_PORT \
  --rmi-port=$MASTER_RMI_PORT \
  --start

#
# Define the starting numbers for slave ports
#
SLAVE_MYSQL_PORT=$MASTER_MYSQL_PORT
SLAVE_THL_PORT=$MASTER_THL_PORT
SLAVE_RMI_PORT=$MASTER_RMI_PORT

#
# Installs the slaves
#

for N in $(myseq 2 $HOW_MANY)
do
    mkdir $TUNGSTEN_BASE/${TSANDBOX_PREFIX}$N    
    SLAVE_THL_PORT=$(($SLAVE_THL_PORT+1))
    SLAVE_RMI_PORT=$(($SLAVE_RMI_PORT+2))
    SLAVE_MYSQL_PORT=$(($SLAVE_MYSQL_PORT+1))

    $TUNGSTEN_INSTALLER \
      --master-slave \
      --cluster-hosts=127.0.0.1 \
      --master-host=127.0.0.1 \
      --master-thl-port=$MASTER_THL_PORT \
      --datasource-port=$SLAVE_MYSQL_PORT \
      --datasource-user=msandbox \
      --datasource-password=msandbox \
      --home-directory=$TUNGSTEN_BASE/${TSANDBOX_PREFIX}$N \
      --datasource-log-directory=$HOME/sandboxes/$MYSQL_GROUP_DIR/node$N/data \
      --datasource-mysql-conf=$HOME/sandboxes/$MYSQL_GROUP_DIR/node$N/my.sandbox.cnf \
      --service-name=$TUNGSTEN_SERVICE \
      --thl-directory=$TUNGSTEN_BASE/${TSANDBOX_PREFIX}$N/tlogs \
      --thl-port=$SLAVE_THL_PORT \
      --rmi-port=$SLAVE_RMI_PORT \
      --start
done 

#
# Creates convenience scripts to handle the database sandboxes
# and the individual Tungsten instances
#
SCRIPT_HEADER1="#!/bin/bash"
SCRIPT_HEADER2="# Created by tungsten-sandbox $VERSION on $(date)"

function add_header {
    echo $SCRIPT_HEADER1 > $1
    echo $SCRIPT_HEADER2 >> $1
}

for N in $( myseq 1 $HOW_MANY)
do
    cd $TUNGSTEN_BASE
    if [ -e n$N ]
    then
        rm -f n$N
    fi
    ln -s $HOME/sandboxes/$MYSQL_GROUP_DIR/n$N n$N
    cd $TUNGSTEN_BASE/${TSANDBOX_PREFIX}$N    
    ln -s $HOME/sandboxes/$MYSQL_GROUP_DIR/node$N/use use
    add_header show_log 
    add_header replicator
    add_header trepctl
    add_header thl
    echo "vim $PWD/tungsten/tungsten-replicator/log/trepsvc.log" >> show_log
    echo "$PWD/tungsten/tungsten-replicator/bin/replicator \$@" >> replicator
    echo "$PWD/tungsten/tungsten-replicator/bin/trepctl -port $(($RMI_BASE_PORT+$N*2)) \$@" >> trepctl
    echo "$PWD/tungsten/tungsten-replicator/bin/thl \$@" >> thl
    chmod +x thl trepctl replicator show_log
done
cd $TUNGSTEN_BASE

for SCRIPT in use stop start clear status send_kill
do
    if [ -e ${SCRIPT}_all ]
    then
        rm -f ${SCRIPT}_all
    fi
    ln -s $HOME/sandboxes/$MYSQL_GROUP_DIR/${SCRIPT}_all db_${SCRIPT}_all
done

add_header clear_tsandbox
echo "$TUNGSTEN_BASE/replicator_all stop" >> clear_tsandbox
echo "$TUNGSTEN_BASE/db_clear_all" >> clear_tsandbox

for N in $(myseq 1 $HOW_MANY)
do
    echo "" >> clear_tsandbox
    echo "rm -rf $TUNGSTEN_BASE/${TSANDBOX_PREFIX}$N/tlogs/$TUNGSTEN_SERVICE/*" >> clear_tsandbox
    echo "rm -rf $TUNGSTEN_BASE/${TSANDBOX_PREFIX}$N/tungsten/tungsten-replicator/log/*" >> clear_tsandbox
done

chmod +x clear_tsandbox

add_header start_tsandbox
echo "$TUNGSTEN_BASE/clear_tsandbox" >> start_tsandbox
echo "$TUNGSTEN_BASE/db_start_all" >> start_tsandbox
echo "$TUNGSTEN_BASE/replicator_all start" >> start_tsandbox
echo "$TUNGSTEN_BASE/trepctl_all services" >> start_tsandbox

chmod +x start_tsandbox

#
# Creates convenience scripts to deal with the tungsten sandbox globally
#
for SCRIPT in trepctl replicator 
do
    add_header ${SCRIPT}_all
    for N in $(myseq 1 $HOW_MANY)
    do
        echo "$PWD/${TSANDBOX_PREFIX}$N/$SCRIPT \$@" >> ${SCRIPT}_all
    done
    chmod +x  ${SCRIPT}_all
done
